package com.me.seckill.config;

import com.me.seckill.enums.ErrorCodeEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;
import org.springframework.web.HttpMediaTypeNotSupportedException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import java.util.List;

/**
 * 全局的统一异常处理，
 *
 * @author ME
 * @date 2020/8/3
 */
@RestControllerAdvice(annotations = RestController.class)
@Slf4j
public class GlobalExceptionHandlerAdvice {

    @ExceptionHandler(value = BusinessException.class)
    public Wrapper<?> handleBusinessException(BusinessException e) {
        return Wrapper.error(e.getCode(), e.getMessage());
    }

    /**
     * RuntimeException 兜底方案
     */
    @ExceptionHandler(RuntimeException.class)
    public Wrapper<?> handleRuntimeException(RuntimeException e) {
        log.error("Controller异常信息：", e);
        return Wrapper.error(ErrorCodeEnum.GL10500.getCode(), e.getMessage());
    }

    /**
     * 其余检测异常 兜底
     */
    @ExceptionHandler(Exception.class)
    public Wrapper<?> handleException(Exception e) {
        log.error("Controller异常信息：", e);
        return Wrapper.error(ErrorCodeEnum.GL10500.getCode(), e.getMessage());
    }

    /**
     * 消息不能读取
     */
    @ExceptionHandler(HttpMessageNotReadableException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public Wrapper<?> handleError(HttpMessageNotReadableException e) {
        log.error("Controller异常信息：", e);
        return Wrapper.error(HttpStatus.BAD_REQUEST.value() ,e.getMessage());
    }

    /**
     * 不支持当前请求方法
     */
    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
    @ResponseStatus(HttpStatus.METHOD_NOT_ALLOWED)
    public Wrapper<?> handleError(HttpRequestMethodNotSupportedException e) {
        log.error("Controller异常信息：", e);
        return Wrapper.error(HttpStatus.METHOD_NOT_ALLOWED.value() ,e.getMessage());
    }

    /**
     * 不支持当前媒体类型
     */
    @ExceptionHandler(HttpMediaTypeNotSupportedException.class)
    @ResponseStatus(HttpStatus.UNSUPPORTED_MEDIA_TYPE)
    public Wrapper<?> handleError(HttpMediaTypeNotSupportedException e) {
        log.error("Controller异常信息：", e);
        return Wrapper.error(HttpStatus.UNSUPPORTED_MEDIA_TYPE.value() ,e.getMessage());
    }

    /**
     * 校验参数注解返回指定的信息 @Valid
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public Wrapper<?> handleError(MethodArgumentNotValidException methodArgumentNotValidException){
        BindingResult bindingResult = methodArgumentNotValidException.getBindingResult();
        String message = "";
        if (bindingResult.hasErrors()){
            List<ObjectError> allErrors = bindingResult.getAllErrors();
            allErrors.forEach(p -> {
                FieldError fieldError = (FieldError) p;
                log.error("{} 字段 {} 校验参数异常：{}",fieldError.getObjectName(),fieldError.getField(),fieldError.getDefaultMessage());
            });
            if (allErrors.size() > 0) {
                FieldError fieldError = (FieldError) allErrors.get(0);
                message = fieldError.getDefaultMessage();
            }
        }

        return Wrapper.error(ErrorCodeEnum.GL10100.getCode(), message);
    }
}
